package com.example.springboot.utils;

import com.example.springboot.entity.FtpInformation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import java.util.UUID;

/**
 * 需要关闭虚拟机防火墙
 * 打开21/22 端口的访问权限
 *
 * @Author:ChenZhangKun
 * @Date: 2021/7/26 16:16
 */
@Component
@Slf4j
public class FtpUtils {
    /**
     * ftp服务器ip地址
     */
    private static final String FTP_ADDRESS = "192.168.25.130";
    /**
     * 端口号
     */
    private static final int FTP_PORT = 21;
    /**
     * 用户名 user 本地虚拟机 redis
     */
    private static String FTP_USERNAME;
    /**
     * 密码 czk19941994 本地虚拟机 redis
     */
    private static String FTP_PASSWORD;
    /**
     * 路径都是/home/加上用户名
     */
    private static String FTP_BASEPATH = "/home/";

    /**
     * @param ftpInformation
     * @param uploadFile
     * @return
     */
    public static String uploadFile(FtpInformation ftpInformation, MultipartFile uploadFile) throws IOException {
        // 拿到用户名和密码
        FTP_USERNAME = ftpInformation.getFTP_USERNAME();
        FTP_PASSWORD = ftpInformation.getFTP_PASSWORD();
        if (Objects.equals("/home/", FTP_BASEPATH)) {
            // 填充路径
            FTP_BASEPATH = FTP_BASEPATH + FTP_USERNAME + "/";
        }
        // 拿到上传文件名
        InputStream inputStream = uploadFile.getInputStream();
        // 拿到原始文件名
        String originalFilename = uploadFile.getOriginalFilename();
        // 拿到扩展名
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 生成一个不重复的文件名
        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

        FTPClient ftpClient = new FTPClient();
        // 设置编码
        ftpClient.setControlEncoding("utf-8");
        try {
            // 连接服务器
            ftpClient.setConnectTimeout(100000 * 1000);
            ftpClient.connect(FTP_ADDRESS, FTP_PORT);
            // 登录
            ftpClient.login(FTP_USERNAME, FTP_PASSWORD);
            // 拿到状态码
            int replyCode = ftpClient.getReplyCode();
            log.info("连接状态码{}", replyCode);
            // 设置二进制文件类型
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            // 设置操作空间
            ftpClient.changeWorkingDirectory(FTP_BASEPATH);
            // 上传文件
            ftpClient.storeFile(fileName, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        } finally {
            if (ftpClient.isConnected()) {
                // 关闭
                ftpClient.disconnect();
            }
        }
        return fileName;
    }
    /**
     * 从FTP服务器下载文件流
     * @param fileName 文件名
     * @return
     */
    public static InputStream download( FtpInformation ftpInformation, String fileName) {

        FTPClient client = new FTPClient();
        try {
            // 连接服务器
            client.connect(FTP_ADDRESS, FTP_PORT);
            // 登录
            client.login(ftpInformation.getFTP_USERNAME(), ftpInformation.getFTP_PASSWORD());
            int reply = client.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {

                // 连接失败
                client.disconnect();
                log.info("FTP服务器配置链接失败！请检查配置");
                return null;
            }

            // 设置被动模式，开通一个端口来传输数据
            client.enterLocalPassiveMode();
            // 切换到下载目录
            final String filePath = "/home/user";
            client.changeWorkingDirectory(filePath);
            log.debug("FTP session指向下载目录：{}", filePath);
            //设置上传文件的类型为二进制类型
            client.setFileType(FTP.BINARY_FILE_TYPE);
//			client.setControlEncoding("utf8");

            // 中文名会下载失败，文件名需转码
            InputStream is = client.retrieveFileStream(new String(fileName.getBytes("gbk"), "ISO-8859-1"));
            if (null == is) {
                log.debug("下载文件：{}失败！读取长度为0！", fileName);
                return null;
            }
            InputStream retIs = copyStream(is);
            is.close();
            client.completePendingCommand();
            log.debug("从FTP服务器下载文件（{}）成功！", fileName);
            return retIs;

        } catch (IOException e) {
            log.info("FTP服务器配置链接失败！错误：{}", e.getMessage());
            e.printStackTrace();
        } finally {

            try {
                if (client.isConnected()) {
                    log.info("从FTP服务器下载文件{}流程结束，关闭链接！", fileName);
                    client.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static InputStream copyStream(InputStream is) throws IOException {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) > -1 ) {
            baos.write(buffer, 0, len);
        }
        baos.flush();

        return new ByteArrayInputStream(baos.toByteArray());
    }


}
